<!DOCTYPE html>
<html>
<!--
Reference:
  https://github.com/jussi-kalliokoski/audiolib.js/wiki/Tutorials%3A-Synthesizing-a-Song
-->
<head>
  <title>AudioLib Test</title>
	<script src="audiolib.min.js" type="text/javascript"></script>
	
	<!-- our audioNoiseInterface code -->
	<script type="text/javascript">
	// audioNoiseInterface constructor
	function _audioNoiseInterface(tempo, notesPerBeat) {
		this.tempo = tempo;
		this.notesPerBeat = notesPerBeat;
		this.noteCount = 0;
	}
	// audioNoiseInterface properties and methods
	_audioNoiseInterface.prototype = {
	
		// A sample stored song as a series of notes with frequency (hz) and duration 
		"simpleSong" : [
			{
				"freq" : 440, // A4
				"dur" : 1/4
			},
			{
				"freq" : 329.63, // E4
				"dur" : 1/4
			},
			{
				"freq" : 440, // A4
				"dur" : 1/4
			},
			{
				"freq" : 440, // A4
				"dur" : 1/4
			}
		],
	
		// The main interface method to the current noise generator.
		// Retrieves output from the noise generator and converts to frequency and duration.
		// The policy that determines the duration will control when this is called again (in time).
		// Sends an event to the videoNoiseInterface with the noise.
		// Chords will return a note with an array of  frequencies.
		// Returns a note object with freq and dur properties.
		// BUT
		// For now, just reference the simple song above, 
		// we will get our next note from the noise function later.			
		"getNextNote" : function () {
			var note = this.simpleSong[this.noteCount++];
		
			// Restart song when end is reached
			if (this.noteCount >= this.simpleSong.length) this.noteCount = 0;
			
			return note;
		},
	
		"getNotesPerBeat" : function () {
			return this.notesPerBeat;
		},
	
		"getTempo" : function () {
			return this.tempo;
		}
	}
	
	// the global instance to the audioNoiseInterface
	var audioNoiseInterface = new _audioNoiseInterface(120, 4);
	</script>
  
	<!-- audioLib code -->
	<script type="text/javascript">
	var   leadNoteLength = 0,
		fade = 0,
		fadePoint = 0,
		dev, sampleRate, lead;
	
	// called from audioCallback
	// inputs
	// gets the next song note
	// gets the song notes per beat and tempo
	// outputs
	// sets outgoing lead note freq and length from song note and song
	// sets fadepoint for this lead note
	// for a chord, we create an array of lead notes.
	function loadNote () {		
		var note = audioNoiseInterface.getNextNote();
		
		// Reset oscillator
		lead.frequency = 0;
		lead.reset();
	
		// Set oscillator frequency
		lead.frequency = note.freq;
	
		// Calculate note length in samples
		leadNoteLength = Math.floor(note.dur * sampleRate * 60 * 
			audioNoiseInterface.getNotesPerBeat() / audioNoiseInterface.getTempo()
			);
	
		// reset fade
		fade = 0;
		
		// define fade point
		fadePoint = leadNoteLength - 300;
	}

	// audioLib calls this when the audio buffer needs filling
	// plays a lead note
	function audioCallback (buffer, channelCount){
		var l = buffer.length,
			sample, note, n, current;
	
		// loop through each sample in the buffer			
		for (current=0; current<l; current+= channelCount){
		
			if (leadNoteLength == 0) loadNote();
		
			// fade in
			if (leadNoteLength > fadePoint){
				fade = 1 - (leadNoteLength-fadePoint)/300;
				// fade out
			} else if (leadNoteLength<300){
				fade = leadNoteLength/300;
			} else {
				fade = 1;
			}
		
			sample = 0;
		
			// Generate oscillator
			lead.generate();
		
			// Get oscillator mix and multiply by .5 to reduce amplitude
			// for a chord, we add the samples together.
			sample = lead.getMix()*0.5*fade;

			// Fill buffer for each channel
			for (n=0; n<channelCount; n++){
				buffer[current + n] = sample;
			}
		
			leadNoteLength -= 1;
		}	
	}
	
	// start the sounds
	var started = 0;
	function startSong() {
		if (started == 0) {
			started = 1;
			// Create an instance of the AudioDevice class
			dev = audioLib.AudioDevice(audioCallback /* callback for the buffer fills */, 2 /* channelCount */);

			sampleRate = dev.sampleRate;
	
			// Create an instance of the Oscillator class... not sure what the 440 is all about - the first note?
			lead = audioLib.Oscillator(sampleRate, 440);
		} 
	}
	</script>
</head>
<body>
  <div>
    <span>Press the button to play song with audiolib.</span>
  </div>
  <input type="button" value="Play Song" onclick="javascript:startSong();" />
  <div>
    <span>This site will only work using Firefox 4+ or Chrome with Web Audio API enabled (navigate to "about:flags" to enable)</span>
  </div>    
</body>
</html>